return 0;
}
+int xb_wait_for_data_to_read(void)
+{
+ struct xenstore_domain_interface *intf = xen_store_interface;
+ return wait_event_interruptible(
+ xb_waitq,
+ intf->rsp_cons != intf->rsp_prod);
+}
+
int xb_read(void *data, unsigned len)
{
struct xenstore_domain_interface *intf = xen_store_interface;
unsigned int avail;
const char *src;
- rc = wait_event_interruptible(
- xb_waitq,
- intf->rsp_cons != intf->rsp_prod);
+ rc = xb_wait_for_data_to_read();
if (rc < 0)
return rc;
/* Low level routines. */
int xb_write(const void *data, unsigned len);
int xb_read(void *data, unsigned len);
+int xb_wait_for_data_to_read(void);
int xs_input_avail(void);
extern struct xenstore_domain_interface *xen_store_interface;
extern int xen_store_evtchn;
return body;
}
-/* Emergency write. */
-void xenbus_debug_write(const char *str, unsigned int count)
-{
- struct xsd_sockmsg msg = { 0 };
-
- msg.type = XS_DEBUG;
- msg.len = sizeof("print") + count + 1;
-
- mutex_lock(&xs_state.request_mutex);
- xb_write(&msg, sizeof(msg));
- xb_write("print", sizeof("print"));
- xb_write(str, count);
- xb_write("", 1);
- mutex_unlock(&xs_state.request_mutex);
-}
-
void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
{
void *ret;
char *body;
int err;
+ err = xb_wait_for_data_to_read();
+ if (err)
+ return err;
+
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (msg == NULL)
return -ENOMEM;
+ /*
+ * We are now committed to reading an entire message. Partial reads
+ * across save/restore leave us out of sync with the xenstore daemon.
+ */
+ down_read(&xs_state.suspend_mutex);
+
err = xb_read(&msg->hdr, sizeof(msg->hdr));
if (err) {
kfree(msg);
- return err;
+ goto out;
}
body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
if (body == NULL) {
kfree(msg);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out;
}
err = xb_read(body, msg->hdr.len);
if (err) {
kfree(body);
kfree(msg);
- return err;
+ goto out;
}
body[msg->hdr.len] = '\0';
&msg->u.watch.vec_size);
if (IS_ERR(msg->u.watch.vec)) {
kfree(msg);
- return PTR_ERR(msg->u.watch.vec);
+ err = PTR_ERR(msg->u.watch.vec);
+ goto out;
}
spin_lock(&watches_lock);
wake_up(&xs_state.reply_waitq);
}
- return 0;
+ out:
+ up_read(&xs_state.suspend_mutex);
+ return err;
}
static int xenbus_thread(void *unused)